package ru.study.thinkin.chapter13;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

abstract class Individual {
	private static long counter;
	private final long id = counter++;
	private String name;

	public long id() {
		return id;
	}

	Individual() {
		name = "NoName";
	}

	Individual(String name) {
		this.name = name;
	}
}

class Pet extends Individual {
	Pet() {
		super();
	}

	Pet(String name) {
		super(name);
	}
}

class Dog extends Pet {
	Dog() {
		super();
	}

	Dog(String name) {
		super(name);
	}
}

class Mutt extends Dog {
	Mutt() {
		super();
	}

	Mutt(String name) {
		super(name);
	}
}

class Pug extends Dog {
	Pug() {
		super();
	}

	Pug(String name) {
		super(name);
	}
}

class Cat extends Pet {
	Cat() {
		super();
	}

	Cat(String name) {
		super(name);
	}
}

abstract class PetCreator {
	private Random rand = new Random();

	public abstract List<Class<? extends Pet>> getTypes();

	public Pet randomPet() {
		int n = rand.nextInt(getTypes().size());
		Pet pet = null;
		try {
			pet = getTypes().get(n).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return pet;
	}

	public Pet[] createArray(int size) {
		Pet[] result = new Pet[size]; 
		for(int i = 0;i<result.length;i++) {
			result[i]=randomPet();			
		}		
		return result;
	}
	public ArrayList<Pet> arrayList(int size) {
		ArrayList<Pet> result = new ArrayList();
		Collections.addAll(result,createArray(size));
		
		return result;
	}
}

class ForNameCreator extends PetCreator {
	private static List<Class<? extends Pet>> types = new ArrayList();
	private static String[] typeNames = {						
		"ru.study.thinkin.chapter13.Pug",
		"ru.study.thinkin.chapter13.Mutt"
	};
	
	private static void loader() {
		try {
			for(String name : typeNames) {
				types.add((Class<? extends Pet>) Class.forName(name));
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	static {loader();}	
	
	@Override
	public List<Class<? extends Pet>> getTypes() {		
		return types;
	}	
}

class LiteralPetCreator extends PetCreator {
	private static final List<Class<? extends Pet>> types = Arrays.asList(
			Dog.class,			
			Cat.class			
			);  	
	@Override
	public List<Class<? extends Pet>> getTypes() {	
		return types;
	}	
	
}

public class PetCount {
	private Map<String,Integer> map = new HashMap<String,Integer>();
	
	private void count(String type) {			
			Integer val = map.get(type);			
			if (val == null){				
				map.put(type,1);
			}else {				
				map.put(type,val+1);				
			}
	}
	private void count(Pet pettype) {	
			count(pettype.getClass().getSimpleName());			
	}	
	
	
	public static void countPets(PetCreator creator){
		PetCount pc = new PetCount();
		int i = 0;
		for(Pet pet:creator.createArray(21)){			
			if (pet.getClass().isAssignableFrom(Dog.class)) {				
				pc.count(pet);	
			}
			if (pet.getClass().isAssignableFrom(Cat.class)) {				
				pc.count(pet);	
			}
			if (pet.getClass().isAssignableFrom(Pug.class)) {				
				pc.count(pet);	
			}			
			if (pet.getClass().isAssignableFrom(Mutt.class)) {				
				pc.count(pet);	
			}			
		}
		System.out.println(pc.map);
	}
	
		
	public static void main(String[] args) {
		countPets(new ForNameCreator());		
	}
}
